package com.planw.beetl.sql.marker;

import com.google.common.collect.Collections2;
import com.intellij.codeInsight.daemon.DefaultGutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.PsiPlainTextImpl;
import com.intellij.psi.templateLanguages.OuterLanguageElementImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import com.planw.beetl.utils.ContextIcons;
import com.planw.beetl.utils.JavaService;
import com.planw.beetl.utils.JavaUtils;
import org.apache.commons.lang.StringUtils;
import org.intellij.plugins.markdown.lang.MarkdownFileViewProvider;
import org.intellij.plugins.markdown.lang.MarkdownLanguage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.event.MouseEvent;
import java.util.*;

public class BeetlSqlMarkdownLineMarkerProvider implements LineMarkerProvider {

    private OuterLanguageElementImpl m_outerLanguageElement;

    @Nullable
    @Override
    public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
        return null;
    }

    @Override
    public void collectSlowLineMarkers(@NotNull List<? extends PsiElement> elements, @NotNull Collection<? super LineMarkerInfo<?>> result) {
        if (elements == null || elements.isEmpty()) {
            return;
        }
//        MarkdownLanguage
        PsiElement elemenFirst = elements.get(0);
        if(!(elemenFirst.getParent() instanceof PsiFile)){
            return;
        }
        if(elemenFirst.getLanguage() == MarkdownLanguage.INSTANCE && elements.size() != 1){
            return;
        }
//        elemenFirst.getContainingFile().;
//        if (elemenFirst instanceof PsiPlainTextImpl) {
//            String file = elemenFirst.getContainingFile().getVirtualFile().getPath();
//            if (StringUtils.equalsIgnoreCase(file, ".js")) {
//                Set<Language> languages = elemenFirst.getContainingFile().getViewProvider().getLanguages();
//                for (Language language : languages) {
//                    if (StringUtils.equalsIgnoreCase(language.getID(), "SQL")) {
//                        return;
//                    }
//                }
//            }
//            if (elemenFirst.getLanguage() != MarkdownLanguage.INSTANCE) {
//                PsiFile fileViewProvider = elemenFirst.getContainingFile();
//                MarkdownFileViewProvider viewProvider = new MarkdownFileViewProvider(fileViewProvider.getManager(),fileViewProvider.getVirtualFile(),false);
//                PsiFile psiFile = viewProvider.getPsi(MarkdownLanguage.INSTANCE);
//                Collection<PsiElement> psiElements = PsiTreeUtil.findChildrenOfType(psiFile, PsiElement.class);
//                // new ArrayList<>(PsiTreeUtil.findChildrenOfType(psiFile, MarkdownHeaderImpl.class))
//                doTextLineMarkerInfo((PsiPlainTextImpl) elemenFirst, result);
//                elements = new ArrayList<>(psiElements);
//            }
//        }
        JavaService javaService = JavaService.getInstance(elemenFirst.getProject());

        String name = elemenFirst.getContainingFile().getName();
        name = StringUtils.capitalize(StringUtils.split(name, ".")[0]);
        List<PsiClass> classMapperList = javaService.findMapperClass(name);
        if(classMapperList == null || classMapperList.isEmpty()){
            return;
        }

        if(elemenFirst.getTextOffset() == 0){
            NavigationGutterIconBuilder<PsiElement> builderMain =
                    NavigationGutterIconBuilder.create(ContextIcons.CONSTANT)
                            .setAlignment(GutterIconRenderer.Alignment.LEFT)
                            .setTargets(classMapperList)
                            .setTooltipTitle("Navigation to target in mapper interface");
            if(elemenFirst.getLanguage() == MarkdownLanguage.INSTANCE){
                if(elemenFirst instanceof OuterLanguageElementImpl){
                    result.add(builderMain.createLineMarkerInfo(elemenFirst));
                }
            } else {
                result.add(builderMain.createLineMarkerInfo(elemenFirst));
            }
        }
//        String text = elemenFirst.getContainingFile().getText();
//        if (!checkIsBeetSql(classMapperList, text)) {
//            return;
//        }

        Map<String, List<PsiMethod>> psiMethodIdMap = javaService.loadMapperPsiMethod(classMapperList);
        List<PsiFile> psiFiles = new ArrayList<>(1);
        psiFiles.add(elemenFirst.getContainingFile());

        Map<String, PsiMethod> psiMethodNameCk = new HashMap<>();
        for (Map.Entry<String, List<PsiMethod>> entry : psiMethodIdMap.entrySet()) {
            if(entry.getValue() != null && !entry.getValue().isEmpty()){
                psiMethodNameCk.put(entry.getKey(),entry.getValue().get(0));
            }
        }

        Map<String, List<PsiElement>> functionNameELStore =  javaService.buildTargetPsiElement(psiFiles,psiMethodNameCk);
        Set<String> addedSqlIds = new HashSet<>();
        for (Map.Entry<String, List<PsiElement>> entry : functionNameELStore.entrySet()) {
            String methodName = entry.getKey();
            if (!psiMethodIdMap.containsKey(methodName) && psiMethodIdMap.containsKey(StringUtils.removeEnd(methodName, "$count"))) {
                methodName = StringUtils.removeEnd(methodName, "$count");
            }
            List<PsiMethod> psiMethods = psiMethodIdMap.get(methodName);
            if (psiMethods == null || psiMethods.isEmpty()) {
                continue;
            }
            addedSqlIds.add(entry.getKey());
            for (PsiElement psiElement : entry.getValue()) {
                NavigationGutterIconBuilder<PsiElement> builder =
                        NavigationGutterIconBuilder.create(ContextIcons.STATEMENT_LINE_MARKER_ICON)
                                .setAlignment(GutterIconRenderer.Alignment.CENTER)
                                .setTargets(psiMethods)
                                .setTooltipTitle("Navigation to target in mapper method");
                result.add(builder.createLineMarkerInfo(psiElement));
            }
        }
//
//
//        String[] sqlRangeArray = StringUtils.split(text, "\n");
//        Set<String> sqlIdSet = new HashSet<>();
//        for (int i = 0; i < sqlRangeArray.length; i++) {
//            String sqlId = sqlRangeArray[i];
//            if (i + 1 < sqlRangeArray.length) {
//                String nextSplitIs = sqlRangeArray[i + 1];
//                if (StringUtils.equals(nextSplitIs.trim(), "===")) {
//                    sqlIdSet.add(sqlId);
//                }
//            }
//        }
//
//
//        Set<String> addedSqlIds = new HashSet<>();
//        for (PsiElement element : elements) {
//            String sqlId = element.getText().trim();
//            if (addedSqlIds.contains(sqlId)) {
//                continue;
//            }
//
//            if (!sqlIdSet.contains(sqlId)) {
//                continue;
//            }
//            String methodName = sqlId;
//            if (!psiMethodIdMap.containsKey(methodName) && psiMethodIdMap.containsKey(StringUtils.removeEnd(methodName, "$count"))) {
//                methodName = StringUtils.removeEnd(methodName, "$count");
//            }
//            List<PsiMethod> psiMethods = psiMethodIdMap.get(methodName);
//            if (psiMethods == null || psiMethods.isEmpty()) {
//                continue;
//            }
//
//            addedSqlIds.add(sqlId);
//            NavigationGutterIconBuilder<PsiElement> builder =
//                    NavigationGutterIconBuilder.create(ContextIcons.STATEMENT_LINE_MARKER_ICON)
//                            .setAlignment(GutterIconRenderer.Alignment.CENTER)
//                            .setTargets(psiMethods)
//                            .setTooltipTitle("Navigation to target in mapper method");
//            result.add(builder.createLineMarkerInfo(element));
//        }
    }


    protected boolean checkIsBeetSql(List<PsiClass> classMapperList, String text) {
        if (classMapperList.isEmpty()) {
            return false;
        }
        return StringUtils.contains(text, "\n===\n");
    }

    protected void doTextLineMarkerInfo(PsiPlainTextImpl plainText, Collection<? super LineMarkerInfo<?>> result) {

    }
}
